 /**
 * 
 */

/**
 * Calculates a given infix expression
 * @author Michael Fildestine ID:309161594
 *
 */
public class InfixCalculator extends Calculator {
	private double result;
	private PeekableStackAsArray myStack = new PeekableStackAsArray();
	
	/**
	 * Evaluate a give infix expression
	 */
	public void evaluate(String expr){
		
		ExpTokenizer tokenizer = new ExpTokenizer(expr);
		while (tokenizer.hasMoreTokens()){                        //as long as there are tokens we use the collapse method on them
			CalcToken token = (CalcToken)tokenizer.nextElement();
			collapse(token);
			myStack.push(token);
		}
		while (myStack.size > 1){                                //While there are more than 1 objects in the stack !
			collapse(null);
		}
		
		result = ((ValueToken)myStack.pop()).getValue();
	}
	
	public double getCurrentResult(){
		return this.result;
	}
	
		
	/**
	 * Collapse tokens until the collapse rule no longer applies
	 * @param token
	 */
	private void collapse(CalcToken token){
		boolean endCollapse = false;
		while(!endCollapse){
			
			if (this.myStack.size >= 3){						//if the stack has at least 3 objects we proceed , else we push the 'token' onto the stack 
				CalcToken e0 = (CalcToken)myStack.peek(0);
				CalcToken e1 = (CalcToken)myStack.peek(1);
				CalcToken e2 = (CalcToken)myStack.peek(2);
				
				//a list of checks 
				boolean e0OpenBracket = e0 instanceof CloseBracket;				
				boolean e1ValueToken = e1 instanceof ValueToken;
				boolean e2CloseBracket = e2 instanceof OpenBracket;
				boolean tokenBinaryOp = token instanceof BinaryOp;
				boolean e0ValueToken = e0 instanceof ValueToken;
				boolean e1BinaryOp = e1 instanceof BinaryOp;
				boolean e2VauleToken = e2 instanceof ValueToken;
				
				//checking if e0,e1,e2 are in the following configuration : '(',valueToken,')' if it is
				//we pop all 3 of them and push the valueToken back
				if (e0OpenBracket && e1ValueToken && e2CloseBracket){
					myStack.pop();
					CalcToken temp = (CalcToken)myStack.pop();
					myStack.pop();
					myStack.push(temp);
				}else if (e0ValueToken && e1BinaryOp && e2VauleToken){     // if e0,e1,e2 are number,operator,number
						
							if (tokenBinaryOp){							// if token is also an operator and the precedence of e1 is greater , we collapse , if not we push token onto the stack.
								
								if (((BinaryOp)token).getPrecedence() <= ((BinaryOp)e1).getPrecedence()){
									
									collapse();
								}else{
									endCollapse = true;
								}
							
							}else{
								collapse();
							}
				}else{
					endCollapse = true;
				}
			
			}else{
				endCollapse = true;;
			}
		}
			
	}
	/**
	 * Private method that is called in case e0,e2 are ValueTokens and e1 is a BinaryOp
	 * it pops the 3 of them out a the stack evaluates the numerical value and pushes it back onto the stack 
	 */
	private void collapse(){
		ValueToken right = (ValueToken)myStack.pop();
		CalcToken op = (CalcToken)myStack.pop();
		ValueToken left = (ValueToken)myStack.pop();
		ValueToken temp = new ValueToken(((BinaryOp)op).operate(left.getValue(), right.getValue()));
		myStack.push(temp);
		
	}
	
//	private boolean validInfixExpr (String expr){
//		boolean ans;
//		
//		if (expr.length() == 1){
//			ans = true;
//		}
//		if ()		
//		
//		
//		
//		return ans;
//	}


}
